package net.wicp.tams.common.binlog.self.constant;

import java.io.IOException;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import lombok.extern.slf4j.Slf4j;
import net.wicp.tams.common.apiext.ByteUtil;
import net.wicp.tams.common.apiext.ByteUtil.AssitRead;
import net.wicp.tams.common.apiext.json.JSONUtil;

/***
 * QueryEvent事件中要解析的
 * 
 * @author zhoujunhui
 *
 */
@Slf4j
public enum StatusVar {
	Q_FLAGS2_CODE("", (byte) 0x00)

	, Q_SQL_MODE_CODE("", (byte) 0x01)

	, Q_CATALOG("", (byte) 0x02)

	, Q_AUTO_INCREMENT("", (byte) 0x03)

	, Q_CHARSET_CODE("", (byte) 0x04)

	, Q_TIME_ZONE_CODE("", (byte) 0x05)

	, Q_CATALOG_NZ_CODE("", (byte) 0x06)

	, Q_LC_TIME_NAMES_CODE("", (byte) 0x07)

	, Q_CHARSET_DATABASE_CODE("", (byte) 0x08)

	, Q_TABLE_MAP_FOR_UPDATE_CODE("", (byte) 0x09)

	, Q_MASTER_DATA_WRITTEN_CODE("", (byte) 0x0a)

	, Q_INVOKERS("", (byte) 0x0b)

	, Q_UPDATED_DB_NAMES("", (byte) 0x0c)

	, Q_MICROSECONDS("", (byte) 0x0d);

	private final String desc;
	private final byte value;// 值

	private StatusVar(String desc, byte value) {
		this.desc = desc;
		this.value = value;
	}

	public static StatusVar get(byte val) {
		for (StatusVar statusVar : StatusVar.values()) {
			if (statusVar.getValue() == val) {
				return statusVar;
			}
		}
		return null;
	}

	/***
	 * 得到一个List
	 * 
	 * @param read
	 * @return
	 */
	public static JSONArray parse(AssitRead read) {
		JSONArray retary = new JSONArray();
		while (read.hasMore()) {
			StatusVar statusVar = get(read.readByte());
			JSONObject tempobj = statusVar.paseStatusVar(read);
			retary.add(tempobj);
		}
		return retary;
	}

	/***
	 * 是否有修改表的数据
	 * 
	 * @param read
	 * @return
	 */
	public static JSONObject parseUpdatedDbNames(AssitRead read) {
		JSONArray ary = parse(read);
		for (int i = 0; i < ary.size(); i++) {
			JSONObject obj = ary.getJSONObject(i);
			if (Q_UPDATED_DB_NAMES.name().equals(obj.get("statusVar"))) {
				return obj;
			}
		}
		return null;
	}

	public JSONObject paseStatusVar(AssitRead read) {
		JSONObject retobj = JSONUtil.packParams("statusVar", this.name());
		switch (this) {
		case Q_FLAGS2_CODE:
			retobj.put("flags", ByteUtil.readLongL(read.readBytes(4)));
			break;
		case Q_SQL_MODE_CODE:
			retobj.put("sqlMode", ByteUtil.readLongL(read.readBytes(8)));
			break;
		case Q_CATALOG:
			ByteUtil.readIntL(read.readBytes(1)); // Length
			try {
				retobj.put("catalogName", read.readStringEndNull());
			} catch (IOException e) {
				log.error("解析StatusVar[Q_CATALOG]出错", e);
			}
			break;
		case Q_AUTO_INCREMENT:
			retobj.put("autoIncrementIncrement", ByteUtil.readIntL(read.readBytes(2)));
			retobj.put("autoIncrementOffset", ByteUtil.readIntL(read.readBytes(2)));
			break;
		case Q_CHARSET_CODE:
			retobj.put("characterSetClient", ByteUtil.readIntL(read.readBytes(2)));
			retobj.put("collationConnection", ByteUtil.readIntL(read.readBytes(2)));
			retobj.put("collationServer", ByteUtil.readIntL(read.readBytes(2)));
			break;
		case Q_TIME_ZONE_CODE:
			int length2 = ByteUtil.readIntL(read.readBytes(1));
			retobj.put("timeZone", ByteUtil.readString(read.readBytes(length2)));
			break;
		case Q_CATALOG_NZ_CODE:
			int length3 = ByteUtil.readIntL(read.readBytes(1));
			retobj.put("catalogName", ByteUtil.readString(read.readBytes(length3)));
			break;
		case Q_LC_TIME_NAMES_CODE:
			retobj.put("lcTimeNames", ByteUtil.readIntL(read.readBytes(2)));
			break;
		case Q_CHARSET_DATABASE_CODE:
			retobj.put("collationDatabase", ByteUtil.readIntL(read.readBytes(2)));
			break;
		case Q_TABLE_MAP_FOR_UPDATE_CODE:
			retobj.put("tableMap", ByteUtil.readLongL(read.readBytes(8)));
			break;
		case Q_MASTER_DATA_WRITTEN_CODE:
			retobj.put("value", ByteUtil.readLongL(read.readBytes(4)));
			break;
		case Q_INVOKERS:
			final int userLength = ByteUtil.readIntL(read.readBytes(1));
			String user = ByteUtil.readString(read.readBytes(userLength));
			final int hostLength = ByteUtil.readIntL(read.readBytes(1));
			String host = ByteUtil.readString(read.readBytes(hostLength));
			retobj.put("user", user);
			retobj.put("host", host);
			break;
		case Q_UPDATED_DB_NAMES:
			int accessedDbCount = ByteUtil.readIntL(read.readBytes(1));
			JSONArray accessedDbs = new JSONArray();
			if (accessedDbCount > 16) {// MAX_DBS_IN_EVENT_MTS
				accessedDbCount = 254;// OVER_MAX_DBS_IN_EVENT_MTS
			} else {
				for (int i = 0; i < accessedDbCount; i++) {
					try {
						accessedDbs.add(read.readStringEndNull());
					} catch (IOException e) {
						log.error("解析StatusVar[Q_UPDATED_DB_NAMES]出错", e);
					}
				}
			}
			retobj.put("accessedDbCount", accessedDbCount);
			retobj.put("accessedDbs", accessedDbs);
			break;
		case Q_MICROSECONDS:
			retobj.put("startUsec", ByteUtil.readIntL(read.readBytes(3)));
			break;
		default:
			break;
		}
		return retobj;
	}

	public String getDesc() {
		return desc;
	}

	public byte getValue() {
		return value;
	}
}
